package com.xtedu.examproject.scheduler.job;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xtedu.examproject.entity.Course;
import com.xtedu.examproject.entity.Examination;
import com.xtedu.examproject.service.CourseService;
import com.xtedu.examproject.service.ExaminationService;
import com.xtedu.examproject.util.RedisUtil;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.stream.Collectors;

public class ExamStatusJob implements Job {
    private ExaminationService examinationService = new ExaminationService();
    private CourseService  courseService = new CourseService();
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {

//        try {
//            // 从Redis中获取所有考试信息
//            List<Examination> examinations = RedisUtil.getObject("examinations", new TypeReference<List<Examination>>() {});
//
//            // 如果Redis中没有数据，则从数据库获取
//            if (examinations == null || examinations.isEmpty()) {
//                System.out.println("Redis中没有考试数据，从数据库获取");
//                examinations = examinationService.getAllExamination();
//            }
//
//            // 检查每个考试的状态
//            LocalDateTime now = LocalDateTime.now();
//            boolean needUpdateCache = false;
//
//            for (Examination exam : examinations) {
//                // 获取考试开始时间
//                Timestamp startTime = exam.getStartTime();
//                if (startTime == null) {
//                    continue;
//                }
//
//                LocalDateTime examStartTime = startTime.toLocalDateTime();
//
//                // 计算当前时间与考试开始时间的差值（分钟）
//                long minutesDiff = ChronoUnit.MINUTES.between(examStartTime, now);
//
//                // 判断考试状态
//                int newState = exam.getState();
//                if (minutesDiff < 0) {
//                    // 考试未开始
//                    newState = 0;
//                } else if (minutesDiff >= exam.getDuration()) {
//                    // 考试已结束
//                    newState = 2;
//                } else {
//                    // 考试进行中
//                    newState = 1;
//                }
//
//                // 如果状态发生变化，更新数据库和Redis
//                if (exam.getState() != newState) {
//                    System.out.println("考试ID " + exam.getId() + " 状态发生变化: " + exam.getState() + " -> " + newState);
//
//                    // 更新考试对象状态
//                    exam.setState(newState);
//
//                    // 更新数据库
//                    try {
//                        examinationService.updateExamination(exam);
//                        System.out.println("考试ID " + exam.getId() + " 数据库状态更新成功");
//                    } catch (Exception e) {
//                        System.err.println("考试ID " + exam.getId() + " 数据库状态更新失败: " + e.getMessage());
//                        e.printStackTrace();
//                    }
//
//                    // 标记需要更新Redis缓存
//                    needUpdateCache = true;
//                }
//            }
//
//            // 如果有状态更新，刷新Redis缓存
//            if (needUpdateCache) {
//                try {
//                    // 重新从数据库获取最新数据
//                    examinations = examinationService.getAllExamination();
//                    // 更新Redis缓存，设置5分钟过期时间
//                    RedisUtil.setObject("examinations", examinations, 300);
//                    System.out.println("Redis缓存已更新");
//                } catch (Exception e) {
//                    System.err.println("更新Redis缓存失败: " + e.getMessage());
//                    e.printStackTrace();
//                }
//            }
//
//            System.out.println("考试状态检查任务执行完成");
//        } catch (Exception e) {
//            System.err.println("执行考试状态检查任务时发生错误: " + e.getMessage());
//            e.printStackTrace();
//        }
        List<Integer> courseIds=RedisUtil.getObject("courseIds",List.class);
        if(courseIds==null){
            try {
                courseIds=courseService.findAllCourse().stream().map(Course::getId).toList();
                RedisUtil.setObject("courseIds", courseIds, 60*60*24);
            } catch (Exception e) {
                //记录日志
                throw new RuntimeException(e);
            }
        }
        courseIds.forEach(courseId->{
            List<Examination> examinations=RedisUtil.getObject("exam:"+courseId, new TypeReference<>() {
            });
            if (examinations==null){
                try {
                    examinations=examinationService.getExaminationByCourseId(courseId);
                } catch (Exception e) {
                    //记录日志
                    throw new RuntimeException(e);
                }
            }
            //检查考试状态
            LocalDateTime now = LocalDateTime.now();
            examinations.forEach(examination -> {
                // 获取考试开始时间
                Timestamp startTime = examination.getStartTime();
                LocalDateTime examStartTime = startTime.toLocalDateTime();
                // 计算当前时间与考试开始时间的差值（分钟）
                long minutesDiff = ChronoUnit.MINUTES.between(examStartTime, now);
                // 判断考试状态
                int newState = examination.getState();
                if (minutesDiff < 0) {
                    // 考试未开始
                    newState = 0;
                } else if (minutesDiff >= examination.getDuration()) {
                    // 考试已结束
                    newState = 2;
                    RedisUtil.del("exam:"+courseId);
                } else {
                    // 考试进行中
                    newState = 1;
                }

                // 如果状态发生变化，更新mysql并使用延时双删保证mysql和redis数据一致性
                if (examination.getState() != newState) {
                    //第一次删除
                    RedisUtil.del("exam:"+courseId);
                    //执行修改mysql
                    examination.setState(newState);
                    try {
                        examinationService.updateExamination(examination);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                    //第二次删除（延时）
                    examDelayedDelete("exam:"+courseId,2000);
                }

            });
        });

    }
    private void examDelayedDelete(String key, long delayMs) {
        new Thread(() -> {
            try {
                Thread.sleep(delayMs);
                RedisUtil.del(key);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }).start();
    }
}